package Day_0222.Spring;

/**
 * @author zxc
 * @date 2023/02/22 11:25
 **/
public class Spring_IOC {
    public static void main(String[] args) {
        /**
         * 谈一谈对于Spring中IOC（控制反转）的理解
         * ===》
         * 1.IOC容器的概念
         * （1）控制反转，即IoC (Inversion of Control)，
         *  它把传统上由程序代码直接操控对象的调用权交给容器，通过容器来实现对象组件的装配和管理。
         *  ===》
         *  所谓的“控制反转”概念，就是对组件对象控制权的转移，从程序代码本身转移到了外部容器。
         *
         * （2）Spring IOC 负责创建对象，管理对象（通过依赖注入（DI），装配对象，配置对象，并且管理这些对象的整个生命周期。
         *
         * 2.控制反转（IOC）的作用
         * （1）管理对象的创建和依赖关系的维护。
         *  对象的创建并不是一件简单的事，在对象关系比较复杂时，如果依赖关系需要程序猿来维护的话，那是相当头疼的
         *
         * （2）解耦，由容器去维护具体的对象
         * （3）托管了类的产生过程，比如我们需要在类的产生过程中做一些处理，
         *  最直接的例子就是代理，如果有容器程序可以把这部分处理交给容器，应用程序则无需去关心类是如何完成代理的.
         *
         * 3.IOC的优点是什么？
         * （1）IOC（控制反转） + DI（依赖注入）把应用的代码量降到最低。
         * （2）它使应用容易测试，单元测试不再需要单例和JNDI查找机制。
         * （3）最小的代价和最小的侵入性，使松散耦合得以实现。
         * （4）IOC容器支持，加载服务时饿汉式初始化和懒加载。
         *
         * 4.Spring IOC的实现机制
         * ===》
         * Spring中 IoC 实现原理就是，工厂模式 + 反射机制。
         *
         * 5.Spring 的 IoC 设计支持以下功能：
         * （1）依赖注入 DI;
         * （2）依赖检查;
         * （3）自动装配对象;
         * （4）支持集合;
         * （5）指定初始化方法和销毁方法;
         * （6）支持回调某些方法（但是需要实现 Spring 接口，略有侵入）;
         * ===》
         * 其中，最重要的就是依赖注入，从 XML 的配置上说，即 ref 标签。对应 Spring RuntimeBeanReference 对象。
         * 对于 IoC 来说，最重要的就是容器。容器管理着 Bean 的生命周期，控制着 Bean 的依赖注入。
         * ===》
         * Spring IOC核心 ：依赖注入(DI) + IOC容器（管理Bean生命周期，同时控制着Bean的依赖注入）
         *
         */
        Fruit f=Factory.getInstance("Day_0222.Spring.Apple");
        if(f != null){
            f.eat();
        }
    }
}
interface Fruit {
    public abstract void eat();
}
class Apple implements Fruit {
    public void eat(){
        System.out.println("Apple");
    }
}
class Orange implements Fruit {
    public void eat(){
        System.out.println("Orange");
    }
}
class Factory {
    public static Fruit getInstance(String ClassName) {
        Fruit f=null;
        try {
            f=(Fruit)Class.forName(ClassName).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return f;
    }
}
